"""
Copyright 2012 Wieser Dietmar, Margit Mutschlechner.

This file is part of Multimedia Social Networking Platform.

Multimedia Social Networking Platform is free software: 
you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Multimedia Social Networking Platform is distributed
in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Multimedia Social Networking Platform.  
If not, see <http://www.gnu.org/licenses/>.

"""

from threading import Timer
from msnp.logger import Logger
from msnp.persistence import PersistenceController, XMLController
from msnp.service.synch.player.amarok import AmarokSynchChanges
from msnp.persistence.mysql import DBValidator, MediaDBController
from msnp.service import utils, synch
from msnp.model.MediaModel import NetSynchChanges
from msnp.model import MediaModel

__synchTimer = None
__restartTimer = True
__isRunning = False

def startSynchChangesTimer():
    """This function starts a Timer object.
    
    If the media database settings are complete the Timer object is started,
    which calls the __executeSynchChanges function after 25 seconds.
    """
    global __synchTimer
    global __restartTimer
    mediasettings = XMLController.readAllSettings().getCurrentUserSettings().getMediaDatabaseSettings()
    host = mediasettings.getHost()
    username = mediasettings.getUser()
    password = mediasettings.getPassword()
    schema = mediasettings.getSchema()
    Logger.info("Try to start synch changes timer...")
    if mediasettings.isComplete() and DBValidator.testDBCredentials(host, username, password):
        if MediaDBController.existsSchemaAndTables(host, username, password, schema):
            Logger.info(" -> done")
            __restartTimer = True
            #TODO for testing 10 seconds, afterwards maybe 60
            __synchTimer = Timer(25, __executeSynchChanges)
            __synchTimer.start()
        else:
            Logger.info(" -> media db is not initialized")
    else:
        Logger.info(" -> unable to start synchchangetimer, db credentials not complete or db not reachable")
    
def runAndStopTimer():
    """This function stops the Timer and runs the Timer's function once."""
    global __synchTimer
    global __restartTimer
    global __isRunning
    stopTimer()
    if __isRunning == False:
        __executeSynchChanges()
        
def stopTimer():
    """This function stops the Timer."""
    global __synchTimer
    global __restartTimer
    global __isRunning
    __restartTimer = False
    if __isRunning == False:
        if __synchTimer != None:
            __synchTimer.cancel()
    
    
def __executeSynchChanges():
    """This function is called by the Timer object.
    
    If the player's database settings are complete it retrieves all changes
    and gives them to an AmarokSynchChangesWriter object for processing
    and writing the changes into the Amarok database.
    Afterwards it starts the Timer object again.
    """
    
    global __restartTimer
    global __isRunning
    
    #TODO lock between synch from amarok to media db and this method
    __isRunning = True
    playersettings = XMLController.readAllSettings().getCurrentUserSettings().getPlayerDatabaseSettings()
    if playersettings.isComplete():
        dbAccessible = PersistenceController.testDBCredentials(playersettings.getHost(), playersettings.getUser(), playersettings.getPassword())
        if dbAccessible:
            Logger.info("Executing SynchChangesTimer")
            insertChanges = PersistenceController.selectSynchInsertChanges()
            updateChanges = PersistenceController.selectSynchUpdateChanges()
            #TODO if there would be more player sort changes here based on the player flag
            amarokWriter = AmarokSynchChanges.AmarokSynchChangesWriter(insertChanges, updateChanges)
            amarokWriter.performChangeComparison()
        
            PersistenceController.deleteSynchChanges()
        
            # log changed medias in net synch changes table
            timestamp = utils.DateFormatter.formatTimeAsFloat()
            changedMediaIds = amarokWriter.getChangedMediaIds()
            if changedMediaIds != None and len(changedMediaIds) > 0:
                for changedMediaId in changedMediaIds:
                    netSynchChange = NetSynchChanges(changedMediaId, None, None, None, timestamp, True, MediaModel.NetSynchChangeSource.PLAYER)
                    PersistenceController.insertNetSynchChange(netSynchChange)
                
                # init sending of updates to network
                synch.NetSynchController.pushMediaContent()
    if __restartTimer:
        startSynchChangesTimer()
    __isRunning = False
